﻿@using BlazorMonaco.Languages
@using FormBuilder.Components.Shared
@using FormBuilder.Dialogs
@using FormBuilder.Helpers
@using FormBuilder.Models
@using System.Text.Json.Nodes
@using System.Text.Json
@using FormBuilder.Models.Layout
@using System.Collections.Specialized
@using FormBuilder.Services
@inject DialogService dialogService
@inject IEnumerable<IFormElementDefinition> definitions
@inject IJSRuntime jsRuntime

<HeadContent>
    @if (Template != null)
    {
        @foreach (var cssStyle in Template.CssStyles)
        {
            if (Template.Name != "Radzen")
            {
                <link id="@cssStyle.Id" rel="stylesheet" href="@uriProvider.GetCssUrl(Template.Id, cssStyle)" />
            }
            else if (cssStyle.Category == TemplateStyleCategories.Custom)
            {
                <style type="text/css">
                    @cssStyle.Value
                </style>

            }
        }

        @foreach (var jsStyle in Template.JsStyles)
        {
            if(jsStyle.Category == TemplateStyleCategories.Lib)
            {
                <script id="@jsStyle.Id" src="@uriProvider.GetJsUrl(Template.Id, jsStyle)" type="text/javascript"></script>
            }
            else
            {
                <script type="text/javascript">
                    @jsStyle.Value
                </script>
            }
        }
    }
</HeadContent>

<MonacoCompletion Context="@context" />

@if(context != null)
{    
    <div class="header">
        <RadzenButton Icon="play_arrow" Text="Debug" Click="@(async () => await LaunchDebug())" ButtonStyle="ButtonStyle.Secondary" />
        <RadzenButton Icon="draft" Text="Json" Click="@(() => SwitchPanel(FormPanelTypes.JSON))" ButtonStyle="ButtonStyle.Secondary" />
        <RadzenButton Icon="css" Text="Css" Click="@(() => SwitchPanel(FormPanelTypes.CSS))" ButtonStyle="ButtonStyle.Secondary" />
        <RadzenButton Icon="data_object" Text="Translations" Click="@(() => SwitchPanel(FormPanelTypes.TRANSLATION))" ButtonStyle="ButtonStyle.Secondary"></RadzenButton>
        @if (CanSave)
        {
            <RadzenButton Icon="save" Text="Save" Style="margin-left: 5px" Click="@(async() => await Save())" Disabled="@isSaveDisabled" />
            <RadzenButton Icon="publish" Text="Publish" Click="@(async() => await Publish())" Disabled="@isPublishDisabled" />
        }
    </div>
    <RadzenSplitter>
        <!-- Toolbox -->
        <RadzenSplitterPane Size="20%">
            <div class="panel-header">
                <RadzenText TextStyle="TextStyle.H6" class="title">Toolbox</RadzenText>
            </div>
            <RadzenStack class="toolbar fullHeight">
                <div class="category">
                    <RadzenText TextStyle="TextStyle.H6" class="title">Elements</RadzenText>
                    <ul class="elements">
                        @foreach (var def in definitions.Where(d => d.Category == ElementDefinitionCategories.ELEMENT))
                        {
                            <li draggable="true" @ondragstart="@(() => HandleDragStart(def))">
                                <div class="icon"><RadzenIcon Icon="@def.Icon" class="icon" /></div><span class="text">@def.Type</span>
                            </li>
                        }
                    </ul>
                </div>
                <div class="category">
                    <RadzenText TextStyle="TextStyle.H6" class="title">Layout</RadzenText>
                    <ul class="elements">
                        @foreach (var def in definitions.Where(d => d.Category == ElementDefinitionCategories.LAYOUT))
                        {
                            <li draggable="true" @ondragstart="@(() => HandleDragStart(def))">
                                <div class="icon"><RadzenIcon Icon="@def.Icon" class="icon" /></div><span class="text">@def.Type</span>
                            </li>
                        }
                    </ul>
                </div>
                <div class="category">
                    <RadzenText TextStyle="TextStyle.H6" class="title">Data</RadzenText>
                    <ul class="elements">
                        @foreach (var def in definitions.Where(d => d.Category == ElementDefinitionCategories.DATA))
                        {
                            <li>
                                <div class="icon"><RadzenIcon Icon="@def.Icon" class="icon" /></div><span class="text">@def.Type</span>
                            </li>
                        }
                    </ul>
                </div>
            </RadzenStack>
        </RadzenSplitterPane>
        <!-- Editor -->
        <RadzenSplitterPane Size="60%">
            <FormViewer @ref=formViewer
            IsEditModeEnabled="true" 
            Context="@context" />
        </RadzenSplitterPane>
        <!-- Properties -->
        <RadzenSplitterPane Size="20%">
            <!-- Version -->
            <div class="panel-header">
                <RadzenText TextStyle="TextStyle.H6" class="title">Version</RadzenText>
            </div>
            <div class="panel-content">
                <RadzenText TextStyle="TextStyle.Subtitle2">Status : <RadzenBadge BadgeStyle="BadgeStyle.Primary" Text="@Enum.GetName(typeof(RecordVersionStatus), Form.Status)" /></RadzenText>
                <RadzenText TextStyle="TextStyle.Subtitle2">Version : <RadzenBadge BadgeStyle="BadgeStyle.Primary" Text="@Form.VersionNumber.ToString()" /></RadzenText>
            </div>
            <!-- Property panel -->
            <div class="panel-header">
                <RadzenText TextStyle="TextStyle.H6" class="title">Properties</RadzenText>
            </div>
            <div class="panel-content">
                @if (panelType == FormPanelTypes.CSS)
                {
                    <CssPanelComponent TemplateSaved="@(async(act) => await HandleTemplateSaved(act))" 
                    TemplateSwitched="@(async(act) => HandleTemplateSwitched(act))"
                    @bind-SelectedTemplate="@context.Template" 
                    AllTemplates="@AllTemplates" 
                    FormId="@Form.Id"></CssPanelComponent>
                }

                @if (panelType == FormPanelTypes.JSON)
                {
                    <JsonPanelComponent @ref=jsonPanelComponent Json="@SerializedForm" JsonChanged="HandleJsonChanged"></JsonPanelComponent>   
                }

                @if(panelType == FormPanelTypes.TRANSLATION)
                {
                    <TranslationPanelComponent AllSupportedLanguages=@SupportedLanguageCodes @bind-SuccessMessageTranslations="@Form.SuccessMessageTranslations" @bind-ErrorMessageTranslations="@Form.ErrorMessageTranslations"></TranslationPanelComponent>
                }
            </div>
        </RadzenSplitterPane>
    </RadzenSplitter>
}

@code {
    [Parameter] public FormRecord Form { get; set; }
    [Parameter] public WorkflowLayout WorkflowLayout { get; set; }
    [Parameter] public Template Template { get; set; }
    [Parameter] public List<Template> AllTemplates { get; set; }
    [Parameter] public List<string> SupportedLanguageCodes { get; set; }
    [Parameter] public EventCallback<ActionState<FormRecord, bool>> Saved { get; set; }
    [Parameter] public EventCallback<ActionState<FormRecord, FormRecord>> Published { get; set; }
    [Parameter] public EventCallback<ActionState<Template, bool>> TemplateSaved { get; set; }
    [Parameter] public EventCallback<Template> TemplateSwitched { get; set; }
    [Parameter] public bool CanSave { get; set; } = true;

    [Inject] public IUriProvider uriProvider { get; set; }
    [Inject] public IFormBuilderJsService formBuilderJsService { get; set; }
    [Inject] public NotificationService notificationService { get; set; }

    WorkflowContext context = null;
    JsonPanelComponent jsonPanelComponent = null;
    FormViewer formViewer = null;
    private bool isSaveDisabled = false;
    private bool isPublishDisabled = false;
    private FormPanelTypes? panelType = null;
    private string SerializedForm { get; set; }

    public void Dispose()
    {
        if (Form != null) Form.Elements.CollectionChanged -= HandleChanged;
    }

    protected async override Task OnParametersSetAsync()
    {
        await base.OnParametersSetAsync();
        if(Form != null)
        {
            context = WorkflowContext.CreateOneStepWorkflow(Form, WorkflowLayout, Template, SupportedLanguageCodes);
            Serialize();
            Form.Elements.CollectionChanged += HandleChanged;
            StateHasChanged();
        }
    }

    private void HandleChanged(object sender, NotifyCollectionChangedEventArgs args) 
        => RefreshJson();

    private void HandleJsonChanged(string json)
    {
        var form = JsonSerializer.Deserialize<FormRecord>(json);
        RefreshForm(form);
    }

    private void HandleDragStart(IFormElementDefinition def)
        => context.FormEditorContext.SelectDefinition(def);

    private async Task HandleTemplateSaved(ActionState<Template, bool> actionState)
    {
        await TemplateSaved.InvokeAsync(actionState);
    }

    private async Task HandleTemplateSwitched(Template template)
    {
        await TemplateSwitched.InvokeAsync(template);
    }

    private Task LaunchDebug()
    {
        var opts = new DialogOptions
        {
            Width = "1200px"
        };
        return dialogService.OpenAsync<DebugFormDialog>("", new Dictionary<string, object>
        {
            { nameof(DebugFormDialog.Form), Form },
            { nameof(DebugFormDialog.Template), Template },
            { nameof(DebugFormDialog.SupportedLanguages), SupportedLanguageCodes }
        }, opts);
    }

    private void SwitchPanel(FormPanelTypes type)
        => panelType = type;

    private async Task Save()
    {
        isSaveDisabled = true;
        await Saved.InvokeAsync(new ActionState<FormRecord, bool>((b) =>
        {
            notificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "The form is updated" });
            isSaveDisabled = false;
        }, Form));
    }

    private async Task Publish()
    {
        isPublishDisabled = true;
        await Published.InvokeAsync(new ActionState<FormRecord, FormRecord>((publishedForm) =>
        {
            notificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "The form is published" });
            // RefreshForm(publishedForm);
            isPublishDisabled = false;
        }, Form));
    }

    private void Serialize() 
        => SerializedForm = Form == null ? "{}" : JsonSerializer.Serialize(Form, new JsonSerializerOptions { WriteIndented = true });

    private async Task LoadCss()
    {
        /*
        var url = uriProvider.GetActiveFormCssUrl(Form.Id);
        using (var httpClient = new HttpClient())
        {
            try
            {
                Css = await httpClient.GetStringAsync(url);
                await formBuilderJsService.RefreshCss(Css);
            }
            catch { }
            }
        */
    }

    private void RefreshForm(FormRecord form)
    {
        Form.Elements.CollectionChanged -= HandleChanged;
        Form = form;
        context = WorkflowContext.CreateOneStepWorkflow(Form, WorkflowLayout, Template, SupportedLanguageCodes);
        formViewer.Set(context);
        RefreshJson();
        Form.Elements.CollectionChanged += HandleChanged;
    }

    private void RefreshJson() 
    {
        Serialize();
        if (jsonPanelComponent == null) return;
        jsonPanelComponent.Refresh(SerializedForm);
    }
}